<template>
  <div class="comm-graph-container">
    <h3>GPU Communication Graph</h3>
    <div class="graph-wrapper">
      <svg :width="graphWidth" :height="graphHeight" class="comm-graph">
        <!-- 连接线 -->
        <line 
          v-for="(conn, idx) in visibleConnections" 
          :key="`conn-${idx}`"
          :x1="getNodeX(conn.source)" 
          :y1="getNodeY(conn.source)"
          :x2="getNodeX(conn.target)" 
          :y2="getNodeY(conn.target)"
          :stroke-width="conn.width"
          stroke="#1890ff"
        />
        
        <!-- 带宽标签 -->
        <text 
          v-for="(conn, idx) in visibleConnections"
          :key="`label-${idx}`"
          :x="(getNodeX(conn.source) + getNodeX(conn.target)) / 2"
          :y="(getNodeY(conn.source) + getNodeY(conn.target)) / 2"
          text-anchor="middle"
          font-size="10"
          fill="#333"
        >
          {{ conn.bandwidth }}G
        </text>
        
        <!-- GPU节点 -->
        <g 
          v-for="(node, idx) in activeNodes"
          :key="`node-${idx}`"
          @mouseenter="hoverNode = node.id"
          @mouseleave="hoverNode = null"
        >
          <circle
            :cx="getNodeX(node.id)"
            :cy="getNodeY(node.id)"
            r="12"
            :fill="getNodeColor(node)"
            stroke="#333"
            stroke-width="1"
          />
          <text
            :x="getNodeX(node.id)"
            :y="getNodeY(node.id) + 4"
            text-anchor="middle"
            font-size="10"
            fill="white"
          >
            {{ node.label }}
          </text>
        </g>
      </svg>
    </div>
  </div>
</template>

<script setup>
import { computed, ref } from 'vue'
import { useTrainingStore } from '../stores/training'

const store = useTrainingStore()
const hoverNode = ref(null)

// 图形尺寸
const graphWidth = computed(() => Math.min(800, window.innerWidth - 350))
const graphHeight = 300

// 获取活跃节点
const activeNodes = computed(() => {
  return Object.values(store.replicaGroups)
    .flatMap(group => Object.values(group.gpus))
    .filter(gpu => gpu.status === 'active')
    .map((gpu, idx) => {
      // 更安全的ID解析方式
      const parts = gpu.id.split('-')
      const groupId = parts.length > 0 ? parts[0] : '0'
      
      return {
        id: gpu.id,
        label: `GPU${idx+1}`,
        group: groupId,
        utilization: gpu.utilization
      }
    })
})

// 获取可见连接
const visibleConnections = computed(() => {
  const connections = []
  const connMap = store.commConnections
  
  if (!connMap) return connections
  
  activeNodes.value.forEach(source => {
    if (connMap[source.id]?.bandwidths) {
      Object.entries(connMap[source.id].bandwidths).forEach(([targetId, bw]) => {
        if (activeNodes.value.some(n => n.id === targetId)) {
          connections.push({
            source: source.id,
            target: targetId,
            bandwidth: bw,
            width: Math.min(4, Math.max(1, bw / 10)) // 带宽越大线越粗
          })
        }
      })
    }
  })
  
  return connections
})

// 节点位置计算 - 添加防御性编程
const getNodeX = (nodeId) => {
  const node = activeNodes.value.find(n => n.id === nodeId)
  if (!node) return 0
  
  try {
    const groupIdx = parseInt(node.group) - 1
    const nodesInGroup = activeNodes.value.filter(n => n.group === node.group)
    const nodeInGroup = nodesInGroup.findIndex(n => n.id === nodeId)
    
    return 100 + groupIdx * (graphWidth.value - 200) / 3 + 
      (nodeInGroup % 3) * 30
  } catch (e) {
    console.error('Error calculating node X position:', e)
    return 100
  }
}

const getNodeY = (nodeId) => {
  const node = activeNodes.value.find(n => n.id === nodeId)
  if (!node) return 0
  
  try {
    const nodesInGroup = activeNodes.value.filter(n => n.group === node.group)
    const nodeInGroup = nodesInGroup.findIndex(n => n.id === nodeId)
    
    return 100 + Math.floor(nodeInGroup / 3) * 60
  } catch (e) {
    console.error('Error calculating node Y position:', e)
    return 100
  }
}

// 节点颜色
const getNodeColor = (node) => {
  if (!node) return '#1890ff'
  if (hoverNode.value === node.id) return '#ff4d4f'
  
  const colors = ['#1890ff', '#52c41a', '#fa8c16', '#722ed1']
  try {
    return colors[parseInt(node.group || '0') % colors.length]
  } catch (e) {
    return colors[0]
  }
}
</script>

<style scoped>
/* 样式保持不变 */
.comm-graph-container {
  margin-top: 30px;
  padding: 15px;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

.comm-graph-container h3 {
  margin-top: 0;
  margin-bottom: 15px;
  font-size: 1.1rem;
  color: #333;
}

.graph-wrapper {
  overflow-x: auto;
}

.comm-graph {
  display: block;
  margin: 0 auto;
  background: #fafafa;
  border-radius: 4px;
}

.comm-graph line {
  opacity: 0.7;
}

.comm-graph text {
  pointer-events: none;
}

.comm-graph circle {
  cursor: pointer;
  transition: fill 0.2s;
}
</style>